/*
 * can.c
 *
 * Created: 01.12.2013 20:12:12
 *  Author: User
 */ 
#include "can.h"
#include "can_msg.h"


uint8_t spic_master_tx_rx(uint8_t c)
{
	// Transmit data in Master mode
	SPIC.DATA=c;
	// Wait for the data to be transmitted/received
	while((SPIC.STATUS & 0x80)==0);
	// Return the received data
	return SPIC.DATA;
}




void mcp_reset(const uint8_t chip)
{
	select(chip);
	spic_master_tx_rx(MCP2515_RESET);
	unselect(chip);
}


uint8_t mcp2515_readRegister(const uint8_t chip,const uint8_t address)
{
	uint8_t ret;

	select(chip) ;
	spic_master_tx_rx(MCP2515_READ);
	spic_master_tx_rx(address);
	ret = spic_master_tx_rx(0x00);
	unselect(chip);
	
	
	return ret;
}



void mcp2515_setRegister(const uint8_t chip,const uint8_t address, const uint8_t value)
{
	select(chip) ;
	spic_master_tx_rx(MCP2515_WRITE);
	spic_master_tx_rx(address);
	spic_master_tx_rx(value);
	unselect(chip);
}

void mcp2515_setRegisterS(const uint8_t chip,const uint8_t address,
const uint8_t values[], const uint8_t n)
{
	uint8_t i;
	
	select(chip) ;
	spic_master_tx_rx(MCP2515_WRITE);
	spic_master_tx_rx(address);
	// mcp2515 has auto-increment of address-pointer
	for (i=0; i<n; i++) {
		spic_master_tx_rx(values[i]);
	}
	unselect(chip);
}



void mcp2515_modifyRegister(const uint8_t chip,const uint8_t address,
const uint8_t mask, const uint8_t data)
{
	select(chip) ;
	spic_master_tx_rx(MCP_BITMOD);
	spic_master_tx_rx(address);
	spic_master_tx_rx(mask);
	spic_master_tx_rx(data);
	unselect(chip);
}



void mcp2515_init(const uint8_t chip)
{
	int ch;
	
	//printf("here");
	mcp_reset(chip);
	//PORTB.OUTCLR=PIN2_bm;
	//printf("here1");
	
	ch = mcp2515_readRegister(chip,MCP2515_CANSTAT);
	//printf("here2");
	printf("CANSTAT[%d]=%d \n\r",chip,ch);
	mcp2515_setRegister(chip,MCP_CNF1, 4);
	mcp2515_setRegister(chip,MCP_CNF2, 0xa9);
	mcp2515_setRegister(chip,MCP_CNF3, 0x86);
	mcp2515_setRegister(chip,MCP2515_CANINTE, 0xff);
	
	
	
	
	// Buffer 0 : Empfangen aller Nachrichten
	mcp2515_setRegister(chip, MCP_RXB0CTRL, 0x60 );
	
	// Buffer 1 : Empfangen aller Nachrichten
	mcp2515_setRegister(chip, MCP_RXB1CTRL, 0x60 );
	
	
	mcp2515_setRegister(chip, MCP_RXM0SIDH, 0 );
	mcp2515_setRegister(chip, MCP_RXM0SIDL, 0 );
	mcp2515_setRegister(chip, MCP_RXM0EID8, 0 );
	mcp2515_setRegister(chip, MCP_RXM0EID0, 0 );
	
	mcp2515_setRegister(chip, MCP_RXM1SIDH, 0 );
	mcp2515_setRegister(chip, MCP_RXM1SIDL, 0 );
	mcp2515_setRegister(chip, MCP_RXM1EID8, 0 );
	mcp2515_setRegister(chip, MCP_RXM1EID0, 0 );
	
	
	
	
	// Deaktivieren der Pins RXnBF Pins (High Impedance State)
	//mcp2515_setRegister(chip, MCP2515_BFPCTRL,20 );
	
	// TXnRTS Bits als Inputs schalten
	mcp2515_setRegister(chip, MCP2515_TXRTSCTRL, 0 );
	
	// Device zurueck in den normalen Modus versetzten
	mcp2515_setRegister(chip, MCP2515_CANCTRL, 0xE);
	
	
}


uint8_t mcp2515_read_rx_status(const uint8_t chip)
{
	uint8_t data;
	
	// /CS des MCP2515 auf Low ziehen
	
	
	
	//data = mcp2515_readRegister(chip,MCP2515_RX_STATUS);
	data = mcp2515_readRegister(chip,0xb0);
	
	// Die Daten werden noch einmal wiederholt gesendet,
	// man braucht also nur eins der beiden Bytes auswerten.
	
	
	// /CS Leitung wieder freigeben
	
	
	return data;
}


void can_send_message(const uint8_t chip,uint8_t *p_message)
{
	
	//uint8_t buf[13];

	
	
	int i;
	
	select(chip) // Select;

	spic_master_tx_rx(MCP2515_WRITE); // command write
	spic_master_tx_rx(0x30); // adress TXBnCTRL
	spic_master_tx_rx(0);
	for(i=0;i<13;i++)
	{
		spic_master_tx_rx(p_message[i]);
		
	}
	
	unselect(chip) // UnSelect;
	mcp2515_modifyRegister(chip,0x30, 8, 8); // if transmitter ready if ((CANBtRd(0x2c)&1)==1)
	
}


uint8_t read_status(const uint8_t chip,const uint8_t cmd)
{
	
	select(chip);
	spic_master_tx_rx(cmd);
	spic_master_tx_rx(0x00);
	unselect(chip);
	
	return 1;
	
}


void mcp2515_readRegisterS(const uint8_t chip,const uint8_t address,
uint8_t values[], const uint8_t n)
{
	uint8_t i;
	
	select(chip);
	spic_master_tx_rx(MCP2515_READ);
	spic_master_tx_rx(address);
	// mcp2515 has auto-increment of address-pointer
	for (i=0; i<n; i++) {
		values[i] = spic_master_tx_rx(0x00);
	}
	unselect(chip);
}



uint8_t can_get_message(const uint8_t chip,CAN_MSG *p_message)
{
	uint8_t i;
	
	uint8_t status;
	uint8_t BF[13];
	memset(BF,0,13);
	// Status auslesen
	select(chip);
	spic_master_tx_rx(0xb0);
	status=spic_master_tx_rx(0x00);
	unselect(chip);
	
	
	 if (status&0x40)
	{
		
		
		select(chip);    // CS Low
		
		
		spic_master_tx_rx(0x90); // command read RxBuffer
		
		for (i=0;i<13;i++)
		{
			BF[i]=spic_master_tx_rx(0);
			
			
		}
		unselect(chip) // UnSelect;
		
		memcpy(p_message,&BF[0],13);
		
		return 1;
		
	}
	
	
	
	return 0;
	
	
}

void mcp2515_clear_interrupt(uint8_t chip)
{
	mcp2515_setRegister(chip,MCP2515_CANINTF, 0x00);
}